import requests
import logging
import os
import string
import time
import random
from typing import Dict, Optional, Tuple
from pathlib import Path

logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)

class ProxyManager:
    def __init__(self):
        self.proxy_host = 'geo.iproyal.com'
        self.proxy_port = '32325'
        self.proxy_username = 'QXj4IJnycx0NeDt2'
        self._base_password = 'XQqJvcmcHSORlRQT'
        self.current_ip = None
        self.plugin_path = None
        self.proxy_password = None
        
        # 可用的美国州列表
        self.us_states = [
            'california',
            'texas',
            'florida',
            'newyork',
            'illinois',
            'pennsylvania',
            'ohio',
            'georgia',
            'michigan',
            'arizona',
            'virginia',
            'washington',
            'newjersey',
            'massachusetts'
        ]
        self.current_state = None
        
        # 添加已使用州的集合
        self.used_states = set()
        
        # 创建插件根目录
        self.plugins_root = os.path.join(os.path.dirname(__file__), "proxy_plugins")
        os.makedirs(self.plugins_root, exist_ok=True)
        
        # 清理旧的插件目录
        self._cleanup_old_plugins()
        
    def _cleanup_old_plugins(self):
        """清理24小时前创建的插件目录"""
        try:
            current_time = time.time()
            for item in os.listdir(self.plugins_root):
                item_path = os.path.join(self.plugins_root, item)
                if os.path.isdir(item_path):
                    # 获取目录的创建时间
                    created_time = os.path.getctime(item_path)
                    # 如果目录创建超过24小时，则删除
                    if current_time - created_time > 24 * 3600:
                        try:
                            import shutil
                            shutil.rmtree(item_path)
                            logger.info(f"已删除旧插件目录: {item_path}")
                        except Exception as e:
                            logger.warning(f"删除旧插件目录失败: {str(e)}")
        except Exception as e:
            logger.error(f"清理旧插件目录时发生错误: {str(e)}")

    def _generate_session_password(self) -> str:
        """生成带会话ID的密码"""
        # 获取可用的州列表
        available_states = [state for state in self.us_states if state not in self.used_states]
        
        # 如果所有州都被使用了，清空已使用集合重新开始
        if not available_states:
            self.used_states.clear()
            available_states = self.us_states
            logger.info("所有州已用完，重置州选择")
        
        # 从可用州中随机选择一个
        self.current_state = random.choice(available_states)
        # 添加到已使用集合
        self.used_states.add(self.current_state)
        logger.info(f"选择州: {self.current_state}，当前已使用的州: {self.used_states}")
            
        # 生成带区域的密码
        self.proxy_password = f"{self._base_password}_country-us_state-{self.current_state}_session-{int(time.time() * 1000)}-{random.randint(1000, 9999)}"
        return self.proxy_password
        
    def create_proxy_auth_extension(self, plugin_path=None) -> str:
        """
        创建代理认证插件
        :param plugin_path: 插件保存路径，如果为None则使用默认路径
        :return: 插件路径
        """
        if plugin_path is None:
            # 使用时间戳和随机数创建新的插件目录，确保唯一性
            timestamp = int(time.time() * 1000)
            random_suffix = random.randint(1000, 9999)
            plugin_path = os.path.join(
                self.plugins_root,
                f"proxy_auth_{self.proxy_host}_{self.proxy_port}_{timestamp}_{random_suffix}"
            )
        
        # 保存插件路径
        self.plugin_path = plugin_path
        
        # 确保插件目录存在
        os.makedirs(plugin_path, exist_ok=True)

        manifest_json = """
        {
            "version": "1.0.0",
            "manifest_version": 2,
            "name": "IPRoyal Proxy",
            "permissions": [
                "proxy",
                "tabs",
                "unlimitedStorage",
                "storage",
                "<all_urls>",
                "webRequest",
                "webRequestBlocking"
            ],
            "background": {
                "scripts": ["background.js"]
            },
            "minimum_chrome_version":"22.0.0"
        }
        """

        background_js = string.Template("""
        var config = {
            mode: "fixed_servers",
            rules: {
                singleProxy: {
                    scheme: "https",
                    host: "${host}",
                    port: parseInt(${port})
                },
                bypassList: []
            }
        };

        chrome.proxy.settings.set({
            value: config,
            scope: "regular"
        }, function() {
            console.log('代理设置已应用');
        });

        function callbackFn(details) {
            return {
                authCredentials: {
                    username: "${username}",
                    password: "${password}"
                }
            };
        }

        chrome.webRequest.onAuthRequired.addListener(
            callbackFn,
            {urls: ["<all_urls>"]},
            ['blocking']
        );
        """).substitute(
            host=self.proxy_host,
            port=self.proxy_port,
            username=self.proxy_username,
            password=self._generate_session_password()  # 使用当前的代理密码
        )

        # 写入manifest.json和background.js文件
        with open(os.path.join(plugin_path, "manifest.json"), "w") as f:
            f.write(manifest_json.strip())
        with open(os.path.join(plugin_path, "background.js"), "w") as f:
            f.write(background_js.strip())

        logger.info(f"代理插件创建成功: {plugin_path}")
        return plugin_path
        
    def get_proxy_config(self) -> Dict[str, str]:
        """获取代理配置"""
        return {
            'http': f'http://{self.proxy_username}:{self._generate_session_password()}@{self.proxy_host}:{self.proxy_port}',
            'https': f'http://{self.proxy_username}:{self._generate_session_password()}@{self.proxy_host}:{self.proxy_port}'
        }
        
    def get_proxy_info(self) -> Tuple[str, str, str, str]:
        """获取代理信息"""
        return self.proxy_host, self.proxy_port, self.proxy_username, self._generate_session_password()
        
    def refresh_ip(self) -> Optional[str]:
        """刷新并获取新IP"""
        try:
            # 随机选择一个新的州
            self.current_state = random.choice(self.us_states)
            
            # 修改密码参数，强制获取新IP
            self.proxy_password = None  # 清除旧密码
            self._generate_session_password()  # 生成新密码
            
            # 如果存在旧的插件目录，删除它
            if self.plugin_path and os.path.exists(self.plugin_path):
                try:
                    import shutil
                    shutil.rmtree(self.plugin_path)
                except Exception as e:
                    logger.warning(f"删除旧插件目录失败: {str(e)}")
            
            proxies = self.get_proxy_config()
            response = requests.get('https://ipv4.icanhazip.com', proxies=proxies)
            self.current_ip = response.text.strip()
            logger.info(f"获取到新IP: {self.current_ip} (州: {self.current_state})")
            return self.current_ip
        except Exception as e:
            logger.error(f"获取新IP失败: {str(e)}")
            return None
            
    def get_current_ip(self) -> Optional[str]:
        """获取当前IP"""
        if not self.current_ip:
            return self.refresh_ip()
        return self.current_ip
        
    def get_proxies(self) -> Dict[str, str]:
        """获取代理配置"""
        return self.get_proxy_config()

    def setup_chrome_options(self, co) -> None:
        """
        设置Chrome选项，添加代理配置
        :param co: ChromiumOptions对象
        """
        try:
            # 创建代理插件
            plugin_path = self.create_proxy_auth_extension()
            logger.info(f"创建代理插件: {plugin_path}")
            
            # 添加代理插件
            co.add_extension(plugin_path)
            
            # 禁用自动化提示
            co.set_argument('--disable-blink-features=AutomationControlled')
            
            # SSL/TLS相关设置
            co.set_argument('--ignore-certificate-errors')
            co.set_argument('--ignore-ssl-errors')
            co.set_argument('--allow-insecure-localhost')
            co.set_argument('--disable-web-security')
            
            # 添加更多配置
            co.set_argument('--disable-gpu')
            co.set_argument('--no-sandbox')
            co.set_argument('--disable-dev-shm-usage')
            co.set_argument('--disable-software-rasterizer')
            co.set_argument('--disable-notifications')
            co.set_argument('--disable-popup-blocking')
            co.set_argument('--disable-automation')
            co.set_argument('--disable-blink-features=AutomationControlled')
            co.set_argument('--disable-extensions-except=' + plugin_path)
            co.set_argument('--load-extension=' + plugin_path)
            
            # 设置浏览器指纹
            co.set_argument('--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36')
            co.set_argument('--lang=zh-CN,zh;q=0.9')
            
            logger.info("Chrome代理选项设置完成")
            
        except Exception as e:
            logger.error(f"设置Chrome代理选项失败: {str(e)}")
            raise 